package com.lujuncheng.tankgame;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;

/**
 * @author LuJuncheng
 * @version 1.0
 * 坦克大战的 绘图区
 */
//为了监听 键盘事件，实现keyListener
//为了让Panel不停的重绘图子弹，需要将MyPanel 实现Running，当一个线程使用
public class MyPanel extends JPanel implements KeyListener, Runnable {
    //定义我的坦克
    Hero hero = null;
    //定义敌人坦克
    Vector<EnemyTank> enemyTanks = new Vector<>();
    int enemyTankSize = 3;
    //定义一个Vector，用于存放炸弹
    //说明,当子弹击中坦克时,加入一个Bomb对象到bombs
    Vector<Bomb> bombs=new Vector<>();
    //定义三张图片，用于显示爆炸效果
    Image image1=null;
    Image image2=null;
    Image image3=null;
    //用于存放当局信息
    Node node=null;

    public MyPanel(String key) {
        //新游戏 或者 继续上局
        newOrOldGame(key);

        //初始化图片对象
        image1=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_1.gif"));
        image2=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_2.gif"));
        image3=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/bomb_3.gif"));

        //这里播放指定的音乐
        new AePlayWave("src/111.wav").start();
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        //背景 填充矩形,默认黑色
        g.fillRect(0, 0, 1000, 750);
        //对局信息
        showInfo(g);
        //画出坦克-封装方法
        drawHero(g);
        drawEnemy(g);
        //如果bombs 集合中有对象，就画出
        drawBombs(g);
    }

    /**
     * 画出敌方坦克
     * @param g
     */
    private void drawEnemy(Graphics g) {
        //画出敌人的坦克，遍历Vector
        for (int i = 0; i < enemyTanks.size(); i++) {
            //从Vector 取出坦克
            EnemyTank enemyTank = enemyTanks.get(i);
            //如果enemyTank存活
            if (enemyTank.isLive){//当敌人坦克是存活的，才画出该坦克
                drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 0);
                drawShots(g,enemyTank);
            }
        }
    }

    /**
     * 画出我方坦克
     * @param g
     */
    private void drawHero(Graphics g) {
        if (hero!=null&&hero.isLive){//若hero存活
            drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);
            drawShots(g,hero);
        }
    }

    /**
     * 画出炸弹
     * @param g
     */
    private void drawBombs(Graphics g) {
        for (int i = 0; i < bombs.size(); i++) {
            //取出炸弹
            Bomb bomb=bombs.get(i);
            //根据当前这个bomb对象去画出对应的图片
            if (bomb.life>6){
                g.drawImage(image1,bomb.x,bomb.y,60,60,this);
            }else if (bomb.life>3){
                g.drawImage(image2,bomb.x,bomb.y,60,60,this);
            }else {
                g.drawImage(image3,bomb.x,bomb.y,60,60,this);
            }
            //让这个炸弹生命值减少
            bomb.lifeDown();
            //如果bomb life 为0，就从bombs 的集合中删除
            if (bomb.life==0){
                bombs.remove(bomb);
            }
        }
    }

    /**
     * 画出子弹
     * @param g
     * @param tank
     */
    private void drawShots(Graphics g, Tank tank) {
        for (int i = 0; i < tank.shots.size(); i++) {
            //取出子弹
            Shot shot = tank.shots.get(i);
            //绘制
            if (shot!=null&&shot.isLive) {
                g.draw3DRect(shot.x, shot.y, 1, 1, false);
            } else {
                //从Vector 移除
                tank.shots.remove(shot);
            }
        }
    }

    /**
     * 新游戏 还是 继续上局
     */
    public void newOrOldGame(String key){
        //先判断记录的文件是否存在
        //如果存在，就正常执行，如果文件不存在，提示，只能开启新游戏，key = "1
        File file = new File(Recorder.recordFile);
        if (file.exists()){
        }else {
            System.out.println("文件不存在，只能开启新游戏");
            key="1";
        }

        switch (key){
            case "1"://新游戏
                node=new Node();
                //初始化敌人的tank
                for (int i = 0; i < enemyTankSize; i++) {
                    EnemyTank enemyTank = new EnemyTank(100 * (i + 1), 0);
                    enemyTank.setDirect(2);
                    //启动敌人线程让它动起来
                    enemyTanks.add(enemyTank);
                    new Thread(enemyTank).start();
                }
                //初始化自己的坦克
                hero = new Hero(400, 100);
                break;
            case "2"://上局游戏
                node = Recorder.getOldGameInfo();
                //启动敌人线程让它动起来
                Vector<Tank> tanks = node.tanks;
                for (Tank tank : tanks) {
                    if (tank instanceof Hero){
                        hero=(Hero) tank;
                        for (Shot shot : hero.shots) {
                            if (shot!=null&&shot.isLive){
                                new Thread(shot).start();
                            }
                        }
                    }else{
                        EnemyTank enemyTank= (EnemyTank) tank;
                        for (int i = 0; i < enemyTank.shots.size(); i++) {
                            Shot shot=enemyTank.shots.get(i);
                            if (shot!=null&&shot.isLive){
                                new Thread(shot).start();
                            }
                        }
                        enemyTanks.add(enemyTank);
                        new Thread(enemyTank).start();
                    }
                }
                break;
            default:
                System.out.println("你的输入有误...");
        }

        //Tank.tanks做防重判断
        if (hero!=null){
            Tank.tanks.add(hero);
        }
        Tank.tanks.addAll(enemyTanks);//加入tanks做重叠判断
        node.tanks=Tank.tanks;//记录
    }

    /**
     * 显示我方击毁敌方坦克的信息
     * @param g
     */
    public void showInfo(Graphics g){
        //画出玩家的总成绩
        g.setColor(Color.BLACK);
        Font font = new Font("宋体", Font.BOLD, 25);
        g.setFont(font);
        g.drawString("您累积击毁敌方坦克",1020,30);
        drawTank(1020,60,g,0,0);//画出一个敌方坦克
        g.setColor(Color.BLACK);
        g.drawString(node.allEnemyTankNum+"",1080,100);
    }

    /**
     * 我方坦克是否被击中
     */
    public void hitHero(){
        //判断是否击中我方坦克
        for (EnemyTank enemyTank : enemyTanks) {
            for (Shot shot : enemyTank.shots) {
                if (shot!=null&&shot.isLive&&hero!=null&&hero.isLive){
                        hitTank(shot,hero);
                }
            }
        }
    }

    /**
     * 敌人坦克是否被击中
     */
    public void hitEnemyTank(){
        //判断是否击中敌人坦克
        if (hero==null||!hero.isLive){
            return;
        }
        Vector<Shot> shots = hero.shots;
        for (Shot shot : shots) {
            if (shot!=null&&shot.isLive){
                for (int i = 0; i < enemyTanks.size(); i++) {
                    EnemyTank enemyTank = enemyTanks.get(i);
                    hitTank(shot,enemyTank);
                }
            }
        }
    }

    /**
     * 判断子弹是否击中坦克
     * @param s 子弹
     * @param tank 坦克
     */
    public void hitTank(Shot s, Tank tank) {
        //判断s击中坦克
        switch (tank.getDirect()) {
            case 0://坦克向上
            case 2://坦克向下
                if (s.x > tank.getX() && s.x < tank.getX() + 40
                        && s.y > tank.getY() && s.y < tank.getY() + 60) {
                    s.isLive = false;
                    tank.isLive = false;
                    if (tank instanceof Hero){
                        hero=null;
                    }else {
                        enemyTanks.remove(tank);
                        Tank.tanks.remove(tank);
                        node.smash();
                    }
                    //创建 Bomb对象，加入到bombs集合
                    Bomb bomb=new Bomb(tank.getX(),tank.getY());
                    bombs.add(bomb);
                }
                break;
            case 1://坦克向右
            case 3://坦克向左
                if (s.x > tank.getX() && s.x < tank.getX() + 60 &&
                        s.y > tank.getY() && s.y < tank.getY() + 40) {
                    s.isLive = false;
                    tank.isLive = false;
                    if (tank instanceof Hero){
                        hero=null;
                    }else {
                        enemyTanks.remove(tank);
                        Tank.tanks.remove(tank);
                        node.smash();
                    }
                    //创建 Bomb对象，加入到bombs集合
                    Bomb bomb=new Bomb(tank.getX(),tank.getY());
                    bombs.add(bomb);
                }
                break;
        }
    }


    /**
     * @param x      坦克的左上角x坐标
     * @param y      坦克的左上角y坐标
     * @param g      画笔
     * @param direct 坦克的类型(上下左右)
     * @param type   坦克的类型
     */
    //编写方法，画出坦克
    public void drawTank(int x, int y, Graphics g, int direct, int type) {
        //根据不同类型的坦克，设置不同的颜色
        switch (type) {
            case 0://敌人的坦克
                g.setColor(Color.CYAN);
                break;
            case 1://我们的坦克
                g.setColor(Color.YELLOW);
                break;
        }

        //根据坦克的方向，来绘制对应的坦克
        //direct表示方向（0：向上 1：向右 2：向下 3：向左）
        switch (direct) {
            case 0://表示向上
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克身体
                g.fillOval(x + 10, y + 20, 20, 20);//画出坦克盖子
                g.drawLine(x + 20, y + 30, x + 20, y);//画出坦克炮筒
                break;
            case 1://表示向右
                g.fill3DRect(x, y, 60, 10, false);//画出坦克左边轮子
                g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克身体
                g.fillOval(x + 20, y + 10, 20, 20);//画出坦克盖子
                g.drawLine(x + 30, y + 20, x + 60, y + 20);//画出坦克炮筒
                break;
            case 2://表示向下
                g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子
                g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克身体
                g.fillOval(x + 10, y + 20, 20, 20);//画出坦克盖子
                g.drawLine(x + 20, y + 30, x + 20, y + 60);//画出坦克炮筒
                break;
            case 3://表示向左
                g.fill3DRect(x, y, 60, 10, false);//画出坦克左边轮子
                g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克右边轮子
                g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克身体
                g.fillOval(x + 20, y + 10, 20, 20);//画出坦克盖子
                g.drawLine(x + 30, y + 20, x, y + 20);//画出坦克炮筒
                break;
            default:
                System.out.println("暂时没有处理");
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    /**
     * hero移动
     * @param e 事件源
     */
    @Override
    public void keyPressed(KeyEvent e) {
        if (hero==null){
            return;
        }
        if (hero.isTouchOhterTank()){
            return;
        }
        if (e.getKeyCode() == KeyEvent.VK_W) {//按下W键
            //改变tank方向
            hero.setDirect(0);
            //使坦克向运动
            hero.move();
        } else if (e.getKeyCode() == KeyEvent.VK_D) {
            hero.setDirect(1);
            hero.move();
        } else if (e.getKeyCode() == KeyEvent.VK_S) {
            hero.setDirect(2);
            hero.move();
        } else if (e.getKeyCode() == KeyEvent.VK_A) {
            hero.setDirect(3);
            hero.move();
        }

        if (e.getKeyCode() == KeyEvent.VK_J&&hero!=null&&hero.isLive) {
            hero.shotEnemy();
        }
        this.repaint();
    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    /**
     * 屏幕刷新
     */
    @Override
    public void run() {//每隔80s,重绘区域，刷新绘图区域，子弹就移动起来
        while (true) {
            try {
                Thread.sleep(80);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //判断敌人坦克是否击中我们坦克
            hitHero();
            //判断是否击中敌人坦克
            hitEnemyTank();

            this.repaint();
        }
    }
}
